//--------------------------------------------------------------------------
// 
//  Copyright (c) Chili Software.  All rights reserved. 
// 
//  File: IdentifierMemberInfoCollection.cs
//
//  Description: Holds all mapped identifier members of the persistent 
//               object.
// 
//--------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;
using System.Collections;

namespace Chili.Opf3.Mapping
{
	/// <summary>
	/// This class represents the list of identifier <see cref="IMemberInfo">IMemberInfo</see> objects for 
	/// the persistent object.
	/// </summary>
	internal sealed class IdentifierMemberInfoCollection : IIdentifierMemberInfoCollection
	{
		private IDictionary<string, IMemberInfo> _fieldnameMemberMapping = new Dictionary<string, IMemberInfo>();
		private IDictionary<string, IMemberInfo> _membernameMemberMapping = new Dictionary<string, IMemberInfo>();
		private List<IMemberInfo> _memberInfos = new List<IMemberInfo>();
		
		/// <summary>
		/// Adds the <see cref="IMemberInfo">IMemberInfo</see> object to the list.
		/// </summary>
		/// <param name="info">The object that is added.</param>
		internal void Add(IMemberInfo info)
		{
			if (info == null)
				throw new ArgumentNullException("info");

			if (!_membernameMemberMapping.ContainsKey(info.Name))
			{
				_fieldnameMemberMapping.Add(info.FieldAttribute.FieldName.ToLower(), info);
				_membernameMemberMapping.Add(info.Name, info);
				_memberInfos.Add(info);
			}
		}

		/// <summary>
		/// Returns the <see cref="IMemberInfo">IMemberInfo</see> object associated with the given field name.
		/// </summary>
		/// <param name="fieldName">The name of the field in the storage.</param>
		/// <returns>An instance of the <see cref="IMemberInfo">IMemberInfo</see> class associated with the given field name.</returns>
		public IMemberInfo GetMemberInfoByField(string fieldName)
		{
			if (fieldName == null)
				throw new ArgumentNullException("fieldName");

			IMemberInfo info = null;
			_fieldnameMemberMapping.TryGetValue(fieldName.ToLower(), out info);

			return info;
		}

		/// <summary>
		/// Returns the <see cref="IMemberInfo">IMemberInfo</see> object associated with the given name of an object member.
		/// </summary>
		/// <param name="memberName">The name of an object member (a property or a field).</param>
		/// <returns>An instance of the <see cref="IMemberInfo">IMemberInfo</see> class associated with the given object member.</returns>
		public IMemberInfo GetMemberInfoByName(string memberName)
		{
			if (memberName == null)
				throw new ArgumentNullException("memberName");

			IMemberInfo info = null;
			_membernameMemberMapping.TryGetValue(memberName, out info);

			return info;
		}

		/// <summary>
		/// Determines whether an element is in the collection.
		/// </summary>
		/// <param name="item">The object to locate in the collection.</param>
		/// <returns>True if item is found in the collection; otherwise, false.</returns>
		public bool Contains(IMemberInfo item)
		{
			return _memberInfos.Contains(item);
		}

		/// <summary>
		/// Copies the entire collection to a compatible one-dimensional array, starting at the specified index of the target array.
		/// </summary>
		/// <param name="array">The one-dimensional System.Array that is the destination of the elements copied from collection. The System.Array must have zero-based indexing.</param>
		/// <param name="arrayIndex">The zero-based index in array at which copying begins.</param>
		public void CopyTo(IMemberInfo[] array, int arrayIndex)
		{
			_memberInfos.CopyTo(array, arrayIndex);
		}

		/// <summary>
		/// Gets the number of elements actually contained in the collection.
		/// </summary>
		public int Count
		{
			get { return _memberInfos.Count; }
		}

		/// <summary>
		/// Returns whether the collection is read-only.
		/// </summary>
		public bool IsReadOnly
		{
			get { return true; }
		}

		/// <summary>
		/// Returns the item at the given index.
		/// </summary>
		/// <param name="index">The index of the item that is returned.</param>
		/// <returns>The item at the given index.</returns>
		public IMemberInfo this[int index]
		{
			get { return _memberInfos[index]; }
		}

		#region IEnumerable<IMemberInfo> Members

		/// <summary>
		/// Returns an enumerator that iterates through the collection.
		/// </summary>
		/// <returns> A enumerator that can be used to iterate through the collection.</returns>
		public IEnumerator<IMemberInfo> GetEnumerator()
		{
			return _memberInfos.GetEnumerator();
		}

		#endregion

		#region IEnumerable Members

		/// <summary>
		/// Returns an enumerator that iterates through a collection.
		/// </summary>
		/// <returns>An enumerator object that can be used to iterate through the collection.</returns>
		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return ((IEnumerable)_memberInfos).GetEnumerator();
		}

		#endregion
	}
}
